package com.hb.A_基础.B_高阶函数和lambda

/**
 * 在不熟悉Kotlin语法的情况下，很容易对fun声明函数、lambda表达式的语法产生混淆，因为
 * 他们都可以存在话括号。
 * 1. fun在没有等号、只有花括号的情况下，是我们最常见的代码款函数体，如果返回非Unit值，必须带return
 * fun foo(x:Int) {print(x)}
 *
 * 2. fun带有等号，是单体表达式的函数体。该情况下省略return
 * fun foo(x:Int,y:Int)=x+y
 *
 * 3. 不管是用val还是fun,如果是等号加括号的语法，那么构建的就是一个lambda表达式，
 * lambda的参数在花括号内部声明。所以，如果左侧是fun,那么就是lambda表达式函数体，也必须通过（）
 * 或invoke来调用lambda.
 * val foo={x:Int,y:Int ->x+y}
 * fun foo(x:Int)={y:Int ->x+y}
 *
 *  闭包:
 *      在kotlin中，你会发现匿名函数体，lambda(以及局部函数、object表达式)在语法上都存在"{}",
 *      由这对花括号包裹的代码块如果访问了外部了外部环境变量则被称为一个闭包。
 *  一个闭包可以被当做参数传递或者直接使用，他可以简单的看成"访问外部环境变量的函数"。lambda是kotlin中
 *  最常见的闭包形式。
 *
 *  与java不一样的地方在于，Kotlin中的闭包不仅可以访问外部变量，还能够对其进行修改，
 */
fun main() {
    println("foo----")
    val foo = { x: Int, y: Int ->
        x + y
    }
    foo.invoke(1, 2)
    foo(1, 2)


    println("bar----")
    fun bar(x: Int) = { y: Int ->
        x + y
    }
    println(bar(1))


    println("-----")
    //kotlin闭包修好
    var sum = 0
    listOf(1, 2, 3).filter {
        it > 0
    }.forEach {
        //不仅可以访问外部变量，还可以对其进行修改
        sum += it
    }
    println("sum=$sum")


    //此外，kotlin还支持一种自运行的lambda语法
//    {
//            x:Int->
//        println(x)
//    }(1)

    println("---------")


    fun get4(fn: (value: String) -> String): String =
        "2"


    fun test(value: String): String =
        value

    fun test2(): String =
        " 12"




//    println(get4(::test))
    /**
     * it：表示函数参数的参数：这里比如value
     */
    val a = get4 {
        println(it)
        //最后一行表示返回值
        "p"

    }
    //println(a+"---get4返回值")

    fun test3(x: Int) = { y: String ->
        {
            println(x)
            y
        }

    }

    println("-----fun-----")
    println(test3(2))
    println(test3(2)("x"))
    println(test3(2)("x")())

}